#ifndef __HIKARI_CONTEXT__
#define __HIKARI_CONTEXT__

#include "hikari.h"
#include "HObjCamera.h"
class ScriptManager;
class HObj;

class HikariContext{
private:
	IrrlichtDevice*device;
	video::IVideoDriver*driver;
	scene::ISceneManager*sceneManager;
	gui::IGUIEnvironment*guiManager;
	HikariEventReceiver*input;
	AnimationManager*animationManager;
	ScriptManager*scriptManager;
	std::list<HObj*>updateableObjects;
	std::list<HObj*>renderUpdatableObjects;
	vector<HObjCamera*>cameras;
	hash_map<long, HObj*>idsToObject;
	u32 currentTime;
	f32 deltaTime;
	btDiscreteDynamicsWorld *collisionWorld;
	hash_map<long, void*>properties;
	NavmeshManager*navmeshManager;
public:
	HikariContext(IrrlichtDevice*device,HikariEventReceiver*input);

	std::wstring getMediaFolder(){
		return std::wstring(L"media/");
	}

	void*getProperty(const wstring&propName){
		return getProperty(propName.c_str());
	}

	void*getProperty(const wchar_t*propName){
		return properties[Utils::hash_WString(propName)];
	}

	void setProperty(const wstring&propName, void*value){
		setProperty(propName.c_str(), value);
	}

	void setProperty(const wchar_t*propName, void*value){
		properties[Utils::hash_WString(propName)]=value;
	}

	void removeProperty(const wstring&propName){
		properties.erase(Utils::hash_WString(propName));
	}

	void setCollisionWorld(btDiscreteDynamicsWorld *world){
		this->collisionWorld=world;
	}

	btDiscreteDynamicsWorld* getCollisionWorld(){
		return collisionWorld;
	}

	f32 getDeltaTime(){
		return deltaTime;
	}

	void setDeltaTime(const f32 deltaTime){
		this->deltaTime=deltaTime;
	}

	u32 getCurrentTime(){
		return currentTime;
	}

	void setCurrentTime(u32 time){
		currentTime=time;
	}

	HObj*getObject(const wchar_t*name){
		return idsToObject[Utils::hash_WString(name)];
	}

	HObj*getObject(const wstring&name){
		return idsToObject[Utils::hash_WString(name.c_str())];
	}

	void addObject(HObj*object, const wstring&name){
		idsToObject[Utils::hash_WString(name.c_str())]=object;
	}

	std::list<HObj*>& getListOfUpdateableObjects(){
		return updateableObjects;
	}

	std::list<HObj*>& getListOfRenderUpdateableObjects(){
		return renderUpdatableObjects;
	}

	vector<HObjCamera*>&getCameras(){
		return cameras;
	}

	void addUpdateableObject(HObj*object){
		updateableObjects.push_back(object);
	}

	void addRenderUpdateableObject(HObj*object){
		renderUpdatableObjects.push_back(object);
	}

	void removeUpdateableObject(HObj*object);

	bool isUpdateableObjectExist(HObj*object);

	void removeRenderUpdateableObject(HObj*object);

	bool isRenderUpdateableObjectExist(HObj*object);

	IrrlichtDevice*getDevice(){
		return device;
	}

	video::IVideoDriver* getDriver(){
		return driver;
	}

	scene::ISceneManager*getSceneManager(){
		return sceneManager;
	}

	ScriptManager* getScriptManager(){
		return scriptManager;
	}

	AnimationManager*getAnimationManager(){
		return animationManager;
	}

	gui::IGUIEnvironment*getGuiManager(){
		return guiManager;
	}

	NavmeshManager*getNavmeshManager(){
		return navmeshManager;
	}

	HikariEventReceiver*getInput(){
		return input;
	}
};
#endif